package com.sy.simpleegg.serialport.lyyegg

import com.sy.simpleegg.ext.logFile
import com.sy.simpleegg.serialport.bean.ComData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.cnbleu.serialport.SerialPort
import java.util.Queue
import java.util.concurrent.LinkedBlockingDeque

/**
 * @author sy
 * @date 2024/11/12 10:37
 * @desc
 */
class LyyEggController(
    portName: String,
    baudrate: SerialPort.BAUDRATE,
    stopb: SerialPort.STOPB,
    datab: SerialPort.DATAB,
    parity: SerialPort.PARITY,
    runHeartBeat: Boolean,
    private val lyyEggListener: LyyEggListener?,
    speed: Long = 10L
): BaseLyyEggController(portName, baudrate, stopb, datab, parity, speed) {

    /**
     * 协程
     */
    private var coroutineScope: CoroutineScope? = null
    /**
     * 控制板心跳线程
     */
    private var heartBeatJob: Job? = null

    private val orderQueue: Queue<String> = LinkedBlockingDeque<String>()
    private var handleJob: Job? = null
    private var isLoop = true
    private var heartLoop = true
    private var handling = false

    /**
     * 心跳间隔，正常-10秒 异常-3秒
     */
    private val HEARTBEAT_INTERVAL_CONNECT: Long = 10 * 1000
    /**
     * 心跳间隔，正常-10秒 异常-3秒
     */
    private val HEARTBEAT_INTERVAL_DISCONNECT: Long = 3 * 1000

    /**
     * 链接状态
     */
    private var isConnect = false
    /**
     * 心跳响应状态，发心跳指令前先设置为false，收到心跳响应设置为true
     */
    private var state: Boolean = true

    private var default_timeout = 10*1000

    private var outResult = -1//0-失败 1-成功 -1-出货中

    init {
        logFile("打开lyy_egg协议版本控制板，串口号=$portName 波特率=$baudrate 停止位=$stopb 数据位=$datab 校验位=$parity 控制板心跳：${if (runHeartBeat) "开启" else "关闭"}")
        coroutineScope = MainScope()
        initHandleJob()
        if (runHeartBeat) heartBeatLoop()
    }

    private fun initHandleJob(){
        handleJob?.cancel()

        handleJob = coroutineScope?.launch (Dispatchers.IO){
            while (isLoop){
                try {
                    run checkSize@{
                        if (orderQueue.size > 0 && !handling) {
                            var sn: String? = null
                            while (orderQueue.poll().also { sn = it } != null) {
                                handling = true

                                if (!isConnect){
//                                    serialControllerListener.onOutCoinsErr()
                                    lyyEggListener?.outResult(false, sn!!, "出货失败：链接中断")
                                    handling = false
                                    return@checkSize
                                }

                                var overCount = 0
                                val interval = 100L
                                val maxCount = default_timeout / interval
                                outResult = -1

                                out(1, sn!!)

                                do {
                                    delay(interval)
                                    overCount ++
                                }while(overCount < maxCount && outResult == -1)

                                lyyEggListener?.outResult(outResult == 1, sn!!, when(outResult){
                                    -1 -> "出货超时"
                                    1 -> "出货成功"
                                    else -> "出货失败"
                                })
                                handling = false
                                delay(1000)
                                return@checkSize
                            }
                        }
                    }
                }catch (e: Exception){
                    e.printStackTrace()
                    logFile("处理出货异常：${e.message}")
                    handling = false
                    lyyEggListener?.outResult(false, "", "出货失败：处理订单异常")
                }
            }
        }
    }

    private fun heartBeatLoop(){
        try {
            heartBeatJob?.cancel()

            heartBeatJob = coroutineScope?.launch (Dispatchers.IO){
                try {
                    run breaking@{
                        while (heartLoop){
                            //出币中，不发送心跳指令，直接返回心跳正常
                            if (handling) {
//                                isConnect = true
                                lyyEggListener?.heartBeat(isConnect)
                                delay(5000)
                                return@breaking
                            }

                            state = true
                            connect()
                            delay(500)
                            isConnect = !state
                            lyyEggListener?.heartBeat(isConnect)

                            if (state){
                                delay(HEARTBEAT_INTERVAL_DISCONNECT)
                            }else{
                                delay(HEARTBEAT_INTERVAL_CONNECT)
                            }
                        }
                    }
                }catch (e: Exception){
                    e.printStackTrace()
                    logFile("心跳处理异常2：" + e.message)
                }
            }
        }catch (e: Exception){
            e.printStackTrace()
            logFile("心跳处理异常：" + e.message)
        }
    }

    /**
     * 出货
     */
    fun out(){
        orderQueue.add(unRepeatSixCode())
    }

    override fun onConnect() {
        state = false
    }

    override fun onRecPrepare(success: Boolean) {

    }

    override fun onOutResult(success: Boolean) {
        outResult = if (success) 1 else 0
    }

    override fun cmdTimeout(comData: ComData) {

    }

    interface LyyEggListener{
        fun heartBeat(isConnect: Boolean)

        fun outResult(success: Boolean, sn: String, msg: String)
    }
}